package com.ztsoft.user.utils;

import cn.hutool.core.text.CharSequenceUtil;
import com.ztsoft.user.pojo.vo.user.SysMenuTree;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 菜单树结构工具
 */
public class MenuTreeUtils {

    private MenuTreeUtils() {
    }

    /**
     * 构建树
     * 1、数据库查出的菜单记录装载在承载菜单的列表中
     * 2、构建树（获取根节点，遍历根节点，对每一个根节点构建子树）
     * 3、得到最终树形菜单
     *
     * @param menuTreeList 需要拼装的树形层级结构数据集合
     * @return 树形层级结构数据集合
     */
    public static List<SysMenuTree> buildMenuTree(List<SysMenuTree> menuTreeList) {
        List<SysMenuTree> menuTreeParentList = new ArrayList<>();
        List<SysMenuTree> menuTreeChildrenList = new ArrayList<>();

        // 获取根节点
        menuTreeList.stream().filter(menuTree -> CharSequenceUtil.hasBlank(menuTree.getParentId())).forEach(menuTreeParentList::add);
        // 获取子节点（排除调根节点，可防止根节点中的空值引发的空指针异常）
        menuTreeList.stream().filter(menuTree -> !menuTreeParentList.contains(menuTree)).forEach(menuTreeChildrenList::add);
        // 构建树
        menuTreeParentList.forEach(menuTreeParent -> buildChildren(menuTreeParent, menuTreeChildrenList));
        return menuTreeParentList;
    }

    /**
     * 构建子树
     *
     * @param menuTreeParent       根节点
     * @param menuTreeChildrenList 子节点集合
     * @return 树形层级结构根节点
     */
    public static SysMenuTree buildChildren(SysMenuTree menuTreeParent, List<SysMenuTree> menuTreeChildrenList) {
        List<SysMenuTree> childrenTree = new ArrayList<>();
        menuTreeChildrenList.stream().filter(menu -> menu.getParentId().equals(menuTreeParent.getValue())).forEach(menuTree -> childrenTree.add(buildChildren(menuTree, menuTreeChildrenList)));
        menuTreeParent.setChildren(childrenTree);
        return menuTreeParent;
    }

    /**
     * 树形层级结构中的数量统计
     *
     * @param treeList 需要统计的树形层级结构数据集合
     */
    public static void getTreeCount(List<SysMenuTree> treeList) {
        for (SysMenuTree sysMenuTree : treeList) {
            // 如果有下级菜单
            if (!sysMenuTree.getChildren().isEmpty()) {
                // 查询并设置子集数量
                sysMenuTree.setCount(String.valueOf(getTreeCount(sysMenuTree, new HashMap<>())));
                getTreeCount(sysMenuTree.getChildren());
            }
        }
    }

    /**
     * 递归统计一个菜单的子节点个数
     *
     * @param sysMenuTree 根节点
     * @param result      全部菜单的子元素的个数
     * @return 根节点的子节点个数
     */
    public static int getTreeCount(SysMenuTree sysMenuTree, Map<String, Object> result) {
        int count = 0;
        if (!sysMenuTree.getChildren().isEmpty()) {
            for (SysMenuTree child : sysMenuTree.getChildren()) {
                //统计当前元素的子节点个数
                count++;
                //统计子节点的孩子总数
                int curCnt = getTreeCount(child, result);
                result.put(child.getValue(), curCnt);
                count += curCnt;
            }
            //返回前记录当前节点的统计个数
            result.put(sysMenuTree.getValue(), count);
        }
        return count;
    }

}